package com.bwie.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bwie.domain.TbUser;
import com.bwie.mapper.TbUserMapper;
import com.bwie.service.TbUserService;
import com.bwie.state.CheckEnum;
import com.bwie.utils.MobileMessageUtil;
import com.bwie.utils.R;
import com.bwie.vo.*;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author 军哥
 * @version 1.0
 * @description: TODO
 * @date 2024/11/12 16:44
 */

@Service
public class TbUserServiceImpl implements TbUserService {

    @Autowired
    TbUserMapper tbUserMapper;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    KafkaTemplate kafkaTemplate;

    @Override
    public TbUser getUserById(Integer userId) {
        return tbUserMapper.selectById(userId);
    }

    @Override
    public R login(LoginInfoVo loginInfoVo) {
        //-- 获取用户信息
        TbUser tbUser = tbUserMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserName, loginInfoVo.getUserName())
        );
        if(tbUser == null) {
            return R.ERROR(404, "用户不存在");
        }

        //-- 验证密码
        if(!tbUser.getUserPass().equals(loginInfoVo.getUserPass())) {
            return R.ERROR(500, "密码错误");
        }

        //-- 生成token
        String token = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "123456")
                .claim("userId", tbUser.getUserId())
                .claim("userName", tbUser.getUserName())
                .claim("nickName", tbUser.getNickName())
                .claim("userRole", tbUser.getUserRole())
                .compact();

        //-- 把token放入缓存，并设置过期时间
        String key = "token-" + tbUser.getUserId();
        stringRedisTemplate.opsForValue().set(key, token, 30, TimeUnit.MINUTES);

        //-- 返回用户信息
        tbUser.setToken(token);
        return R.OK(tbUser);
    }

    @Override
    public R shopperRegister(TbUser tbUser) {
        //-- 验证用户名是否已存在
        TbUser user = tbUserMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserName, tbUser.getUserName())
        );
        if(user != null) {
            return R.ERROR(500, "用户名已存在");
        }

        //-- 验证用户手机号是否存在
        TbUser user2 = tbUserMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserMobile, tbUser.getUserMobile())
        );
        if(user2 != null) {
            return R.ERROR(500, "手机号已存在");
        }

        //-- 保存用户信息
        tbUser.setUserRole(RoleEnum.ROLE_SHOPPER.getCode());
        tbUser.setCreateTime(new Date());
        tbUser.setShopper(0);
        tbUserMapper.insert(tbUser);
        return R.OK();
    }

    @Override
    public R sendCode(String mobile) {
        //-- 生成验证码
        String code = RandomUtil.randomNumbers(4);
        System.out.println("验证码：" + code);

        //-- 把验证码放入缓存(验证码过期时间是5分钟)
        stringRedisTemplate.opsForValue().set(mobile, code, 5, TimeUnit.MINUTES);

        //-- 发送短信
        Boolean ok = MobileMessageUtil.sendMobileMessage(mobile, code);
        if(!ok) {
            // 验证码发送失败，再次发送
            MobileMessageUtil.sendMobileMessage(mobile, code);
        }

        return R.OK();
    }

    @Override
    public R shopperLogin(MobileLoginVo mobileLoginVo) {
        //-- 校验验证码
        String key = mobileLoginVo.getUserMobile();
        String redisCode = stringRedisTemplate.opsForValue().get(key);
        if(redisCode == null) {
            return R.ERROR(500, "验证码已过期");
        }
        if(!redisCode.equals(mobileLoginVo.getUserCode())) {
            return R.ERROR(500, "验证码错误");
        }

        //-- 根据手机号获取用户信息
        TbUser tbUser = tbUserMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserMobile, mobileLoginVo.getUserMobile())
        );
        if(tbUser == null) {
            return R.ERROR(500, "用户不存在");
        }

        //-- 生成token，并放入缓存：30分钟过期
        String token = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "123456")
                .claim("userId", tbUser.getUserId())
                .claim("userName", tbUser.getUserName())
                .claim("nickName", tbUser.getNickName())
                .claim("userRole", tbUser.getUserRole())
                .compact();

        String tokenKey = "token-" + tbUser.getUserId();
        stringRedisTemplate.opsForValue().set(tokenKey, token, 30, TimeUnit.MINUTES);

        //-- 返回用户信息
        tbUser.setUserPass(null);
        tbUser.setToken(token);
        return R.OK(tbUser);
    }

    @Override
    public R getShopperList(PageInfoVo pageInfoVo) {
        //-- 构造分页
        Page<TbUser> page = new Page<>(pageInfoVo.getPageNum(), pageInfoVo.getPageSize());

        //-- 获取列表
        QueryWrapper<TbUser> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(TbUser::getUserRole, RoleEnum.ROLE_SHOPPER.getCode()).orderByDesc(TbUser::getUserId);

        // 关键字查询：多字段查询
        if(!StringUtils.isEmpty(pageInfoVo.getKeyWord())) {
            wrapper.lambda().like(TbUser::getUserName, pageInfoVo.getKeyWord())
                    .or().like(TbUser::getNickName, pageInfoVo.getKeyWord())
                    .or().like(TbUser::getUserMobile, pageInfoVo.getKeyWord());
        }

        Page<TbUser> userPage = tbUserMapper.selectPage(page, wrapper);

        //-- 返回数据
        return R.OK(userPage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R getUserInfo(Integer userId) {
        TbUser tbUser = tbUserMapper.selectById(userId);
        return R.OK(tbUser);
    }

    @Override
    public R checkShopper(TbUser tbUser) {
        //-- 1 获取商户信息
        TbUser user = tbUserMapper.selectById(tbUser.getUserId());
        if(user == null) {
            return R.ERROR(404, "用户不存在");
        }

        //-- 2 审核商户
        user.setShopper(tbUser.getShopper());
        user.setCheckReason(tbUser.getCheckReason());
        tbUserMapper.updateById(user);

        //--3 审核不通过，发送短信通知用户
        if(tbUser.getShopper().equals(CheckEnum.CHECK_FAIL.getCode())) {
            String mobile = user.getUserMobile();
            String content = "您的商户申请审核不通过，原因：" + tbUser.getCheckReason();
            MobileMessageUtil.sendMobileMessage(mobile, content);

            MessageVo messageVo = new MessageVo();
            messageVo.setMsgId(UUID.randomUUID().toString());

            JSONObject msgBody = new JSONObject();
            msgBody.put("mobile", mobile);
            msgBody.put("content", content);

            messageVo.setMsgBody(msgBody.toJSONString());

            kafkaTemplate.send("topic-check", JSON.toJSONString(messageVo));
        }

        return R.OK();
    }

    @Override
    public R deleteShopper(Integer userId) {
        tbUserMapper.deleteById(userId);
        return R.OK();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deleteShoppers(List<TbUser> tbUsers) {
        for (TbUser tbUser : tbUsers) {
            tbUserMapper.deleteById(tbUser.getUserId());
        }
        return R.OK();
    }

    @Override
    public R updateShopper(TbUser tbUser) {
        //-- 校验用户名是否已存在
        TbUser user = tbUserMapper.selectById(tbUser.getUserId());
        if(user == null) {
            return R.ERROR(500, "用户不存在");
        }

        //-- 修改商户信息
        tbUserMapper.updateById(tbUser);
        return R.OK();
    }

    @Override
    public R getNumberForWeek() {

        List<NumDayVo> numberForWeek = tbUserMapper.getNumberForWeek();

        // 柱状图和折线图数据
        ArrayList<String> xData = new ArrayList<>();
        ArrayList<Double> yData = new ArrayList<>();

        ArrayList<PieDataVo> pieData = new ArrayList<>();

        for (NumDayVo numDayVo : numberForWeek) {
            // 折线图和柱状图数据
            xData.add(numDayVo.getDayName());
            yData.add(numDayVo.getNumValue());

            // 饼图数据
            PieDataVo pieDataVo = new PieDataVo();
            pieDataVo.setName(numDayVo.getDayName());
            pieDataVo.setValue(numDayVo.getNumValue());
            pieData.add(pieDataVo);
        }

        // 数据返回
        HashMap<String, Object> map = new HashMap<>();
        map.put("xData", xData);
        map.put("yData", yData);
        // 饼图数据
        map.put("pieData", pieData);

        return R.OK(map);
    }
}
